home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1995 June / MacFormat 25.iso / Shareware City / Developers / OutOfPhase1.1 Source / OutOfPhase Folder / AlgoSampObject.c < prev    next >
Text File  |  1994-12-27  |  44KB  |  1,536 lines

  1. /* AlgoSampObject.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "AlgoSampObject.h"
  31. #include "AlgoSampList.h"
  32. #include "Memory.h"
  33. #include "DataMunging.h"
  34. #include "CodeCenter.h"
  35. #include "PcodeStack.h"
  36. #include "PcodeSystem.h"
  37. #include "MainWindowStuff.h"
  38. #include "Alert.h"
  39. #include "Numbers.h"
  40. #include "SampleStorageActual.h"
  41. #include "AlgoSampWindow.h"
  42. #include "CompilerRoot.h"
  43. #include "FunctionCode.h"
  44. #include "BufferedFileInput.h"
  45. #include "BufferedFileOutput.h"
  46.  
  47.  
  48. struct AlgoSampObjectRec
  49.     {
  50.         MyBoolean                                DataModified;
  51.  
  52.         char*                                        Name;
  53.         char*                                        AlgoSampFormula;
  54.  
  55.         MyBoolean                                NeedsToBeRebuilt;
  56.         SampleStorageActualRec*    SampleData; /* NIL if not built */
  57.         NumBitsType                            NumBits;
  58.         NumChannelsType                    NumChannels;
  59.  
  60.         long                                        Origin;
  61.         long                                        LoopStart1;
  62.         long                                        LoopStart2;
  63.         long                                        LoopStart3;
  64.         long                                        LoopEnd1;
  65.         long                                        LoopEnd2;
  66.         long                                        LoopEnd3;
  67.         long                                        SamplingRate;
  68.         double                                    NaturalFrequency;
  69.  
  70.         AlgoSampWindowRec*            AlgoSampWindow;
  71.  
  72.         struct CodeCenterRec*        CodeCenter;
  73.         struct MainWindowRec*        MainWindow;
  74.         AlgoSampListRec*                AlgoSampList;
  75.  
  76.         short                                        SavedWindowXLoc;
  77.         short                                        SavedWindowYLoc;
  78.         short                                        SavedWindowWidth;
  79.         short                                        SavedWindowHeight;
  80.     };
  81.  
  82.  
  83. /* allocate and create a new empty algorithmic sample object, with reasonable defaults */
  84. AlgoSampObjectRec*        NewAlgoSampObject(struct CodeCenterRec* CodeCenter,
  85.                                                 struct MainWindowRec* MainWindow,
  86.                                                 struct AlgoSampListRec* AlgoSampList)
  87.     {
  88.         AlgoSampObjectRec*    AlgoSampObj;
  89.  
  90.         AlgoSampObj = (AlgoSampObjectRec*)AllocPtrCanFail(sizeof(AlgoSampObjectRec),
  91.             "AlgoSampObjectRec");
  92.         if (AlgoSampObj == NIL)
  93.             {
  94.              FailurePoint1:
  95.                 return NIL;
  96.             }
  97.         AlgoSampObj->Name = StringToBlockCopy("untitled");
  98.         if (AlgoSampObj->Name == NIL)
  99.             {
  100.              FailurePoint2:
  101.                 ReleasePtr((char*)AlgoSampObj);
  102.                 goto FailurePoint1;
  103.             }
  104.         AlgoSampObj->AlgoSampFormula = StringToBlockCopy(
  105.             "# samplingrate, origin, loopstart1, loopstart2, loopstart3 : integer\x0a"
  106.             "# loopend1, loopend2, loopend3 : integer\x0a"
  107.             "# naturalfrequency : double; [data | leftdata, rightdata] : fixedarray\x0a");
  108.         if (AlgoSampObj->AlgoSampFormula == NIL)
  109.             {
  110.              FailurePoint3:
  111.                 ReleasePtr(AlgoSampObj->Name);
  112.                 goto FailurePoint2;
  113.             }
  114.         AlgoSampObj->DataModified = False;
  115.         AlgoSampObj->NeedsToBeRebuilt = True;
  116.         AlgoSampObj->SampleData = NIL;
  117.         AlgoSampObj->Origin = 0;
  118.         AlgoSampObj->LoopStart1 = 0;
  119.         AlgoSampObj->LoopStart2 = 0;
  120.         AlgoSampObj->LoopStart3 = 0;
  121.         AlgoSampObj->LoopEnd1 = 0;
  122.         AlgoSampObj->LoopEnd2 = 0;
  123.         AlgoSampObj->LoopEnd3 = 0;
  124.         AlgoSampObj->SamplingRate = 44100;
  125.         AlgoSampObj->NaturalFrequency = 261.625565300598635;
  126.         AlgoSampObj->AlgoSampWindow = NIL;
  127.         AlgoSampObj->CodeCenter = CodeCenter;
  128.         AlgoSampObj->MainWindow = MainWindow;
  129.         AlgoSampObj->AlgoSampList = AlgoSampList;
  130.         AlgoSampObj->NumBits = eSample16bit;
  131.         AlgoSampObj->NumChannels = eSampleMono;
  132.         AlgoSampObj->SavedWindowXLoc = 0;
  133.         AlgoSampObj->SavedWindowYLoc = 0;
  134.         AlgoSampObj->SavedWindowWidth = 0;
  135.         AlgoSampObj->SavedWindowHeight = 0;
  136.         return AlgoSampObj;
  137.     }
  138.  
  139.  
  140. /* dispose of an algorithmic sample object */
  141. void                                    DisposeAlgoSampObject(AlgoSampObjectRec* AlgoSampObj)
  142.     {
  143.         CheckPtrExistence(AlgoSampObj);
  144.         if (AlgoSampObj->AlgoSampWindow != NIL)
  145.             {
  146.                 DisposeAlgoSampWindow(AlgoSampObj->AlgoSampWindow);
  147.                 ERROR(AlgoSampObj->AlgoSampWindow != NIL,PRERR(AllowResume,
  148.                     "DisposeAlgoSampObject:  window thing not NIL after DisposeAlgoSampWindow"));
  149.             }
  150.         ReleasePtr(AlgoSampObj->Name);
  151.         ReleasePtr(AlgoSampObj->AlgoSampFormula);
  152.         if (AlgoSampObj->SampleData != NIL)
  153.             {
  154.                 DisposeSampleStorageActual(AlgoSampObj->SampleData);
  155.             }
  156.         ReleasePtr((char*)AlgoSampObj);
  157.     }
  158.  
  159.  
  160. /* find out if algorithmic sample object has been modified */
  161. MyBoolean                            HasAlgoSampObjectBeenModified(AlgoSampObjectRec* AlgoSampObj)
  162.     {
  163.         CheckPtrExistence(AlgoSampObj);
  164.         if (AlgoSampObj->AlgoSampWindow != NIL)
  165.             {
  166.                 return AlgoSampObj->DataModified
  167.                     || HasAlgoSampWindowBeenModified(AlgoSampObj->AlgoSampWindow);
  168.             }
  169.          else
  170.             {
  171.                 return AlgoSampObj->DataModified;
  172.             }
  173.     }
  174.  
  175.  
  176. static FunctionParamRec        StereoArgList[] =
  177.     {
  178.         {"loopstart1",eInteger},
  179.         {"loopstart2",eInteger},
  180.         {"loopstart3",eInteger},
  181.         {"loopend1",eInteger},
  182.         {"loopend2",eInteger},
  183.         {"loopend3",eInteger},
  184.         {"origin",eInteger},
  185.         {"samplingrate",eInteger},
  186.         {"naturalfrequency",eDouble},
  187.         {"leftdata",eArrayOfFixed},
  188.         {"rightdata",eArrayOfFixed}
  189.     };
  190. #define STEREOARGLISTLENGTH (sizeof(StereoArgList) / sizeof(StereoArgList[0]))
  191.  
  192.  
  193. static FunctionParamRec        MonoArgList[] =
  194.     {
  195.         {"loopstart1",eInteger},
  196.         {"loopstart2",eInteger},
  197.         {"loopstart3",eInteger},
  198.         {"loopend1",eInteger},
  199.         {"loopend2",eInteger},
  200.         {"loopend3",eInteger},
  201.         {"origin",eInteger},
  202.         {"samplingrate",eInteger},
  203.         {"naturalfrequency",eDouble},
  204.         {"data",eArrayOfFixed}
  205.     };
  206. #define MONOARGLISTLENGTH (sizeof(MonoArgList) / sizeof(MonoArgList[0]))
  207.  
  208.  
  209. /* build the algorithmic sample.  returns True if successful. */
  210. MyBoolean                            AlgoSampObjectBuild(AlgoSampObjectRec* AlgoSampObj)
  211.     {
  212.         char*                                Blob;
  213.         PcodeRec*                        FuncCode;
  214.         CompileErrors                Error;
  215.         long                                LineNumber;
  216.         ParamStackRec*            ParamList;
  217.         EvalErrors                    OtherError;
  218.         OpcodeRec*                    ErrorOpcode;
  219.         long                                OffendingInstruction;
  220.         DataTypes                        ReturnType;
  221.  
  222.         CheckPtrExistence(AlgoSampObj);
  223.  
  224.         /* make sure we are unbuilt */
  225.         AlgoSampObjectUnbuild(AlgoSampObj);
  226.         ERROR(AlgoSampObj->SampleData != NIL,PRERR(ForceAbort,
  227.             "AlgoSampObjectBuild:  called AlgoSampObjectUnbuild but object still exists"));
  228.  
  229.         /* bring the world up to date */
  230.         if (!MainWindowMakeUpToDateFunctions(AlgoSampObj->MainWindow))
  231.             {
  232.                 return False;
  233.             }
  234.  
  235.         /* prepare the text blob to be evaluated */
  236.         Blob = AlgoSampObjectGetFormulaCopy(AlgoSampObj);
  237.         if (Blob == NIL)
  238.             {
  239.              FailurePoint1:
  240.                 AlertHalt("There is not enough memory available to compile the algorithmic "
  241.                     "sample generator function.",NIL);
  242.                 return False;
  243.             }
  244.  
  245.         /* perform compilation */
  246.         Error = CompileSpecialFunction((AlgoSampObjectGetNumChannels(AlgoSampObj)
  247.             == eSampleStereo) ? StereoArgList : MonoArgList,(AlgoSampObjectGetNumChannels(
  248.             AlgoSampObj) == eSampleStereo) ? STEREOARGLISTLENGTH : MONOARGLISTLENGTH,
  249.             &LineNumber,&ReturnType,Blob,&FuncCode);
  250.         ReleasePtr(Blob);
  251.         /* show the error message if there is one */
  252.         if (Error != eCompileNoError)
  253.             {
  254.                 if (!AlgoSampObjectOpenWindow(AlgoSampObj))
  255.                     {
  256.                         AlertHalt("A compile error occurred but there is not enough memory "
  257.                             "available to display the error message.",NIL);
  258.                         return False;
  259.                     }
  260.                 AlgoSampWindowHiliteLine(AlgoSampObj->AlgoSampWindow,LineNumber - 1);
  261.                 AlertHalt("A compile error occurred:  _",GetCompileErrorString(Error));
  262.                 return False;
  263.             }
  264.  
  265.         /* try to evaluate the code */
  266.         ParamList = NewParamStack();
  267.         if (ParamList == NIL)
  268.             {
  269.              SecondFailurePoint1:
  270.                 DisposePcode(FuncCode);
  271.                 AlertHalt("There is not enough memory available to evaluate the algorithmic "
  272.                     "sample generator function.",NIL);
  273.                 return False;
  274.             }
  275.         /* add a space for the return value */
  276.         if (!AddIntegerToStack(ParamList,0))
  277.             {
  278.              SecondFailurePoint2:
  279.                 DisposeParamStack(ParamList);
  280.                 goto SecondFailurePoint1;
  281.             }
  282.         /* add the special parameters (SymbolStack order MUST be the same */
  283.         /* order as that used for the Parameterlist) */
  284.         /* loopstart */
  285.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopStart1(AlgoSampObj)))
  286.             {
  287.                 goto SecondFailurePoint2;
  288.             }
  289.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopStart2(AlgoSampObj)))
  290.             {
  291.                 goto SecondFailurePoint2;
  292.             }
  293.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopStart3(AlgoSampObj)))
  294.             {
  295.                 goto SecondFailurePoint2;
  296.             }
  297.         /* loopend */
  298.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopEnd1(AlgoSampObj)))
  299.             {
  300.                 goto SecondFailurePoint2;
  301.             }
  302.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopEnd2(AlgoSampObj)))
  303.             {
  304.                 goto SecondFailurePoint2;
  305.             }
  306.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopEnd3(AlgoSampObj)))
  307.             {
  308.                 goto SecondFailurePoint2;
  309.             }
  310.         /* origin */
  311.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetOrigin(AlgoSampObj)))
  312.             {
  313.                 goto SecondFailurePoint2;
  314.             }
  315.         /* samplingrate */
  316.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetSamplingRate(AlgoSampObj)))
  317.             {
  318.                 goto SecondFailurePoint2;
  319.             }
  320.         /* basefrequency */
  321.         if (!AddDoubleToStack(ParamList,AlgoSampObjectGetNaturalFrequency(AlgoSampObj)))
  322.             {
  323.                 goto SecondFailurePoint2;
  324.             }
  325.         /* data */
  326.         if (AlgoSampObjectGetNumChannels(AlgoSampObj) == eSampleStereo)
  327.             {
  328.                 char*                    Buffer;
  329.  
  330.                 Buffer = AllocPtrCanFail(0,"degeneratesample");
  331.                 if (Buffer == NIL)
  332.                     {
  333.                         goto SecondFailurePoint2;
  334.                     }
  335.                 if (!AddArrayToStack(ParamList,Buffer))
  336.                     {
  337.                         ReleasePtr(Buffer);
  338.                         goto SecondFailurePoint2;
  339.                     }
  340.                 Buffer = AllocPtrCanFail(0,"degeneratesample");
  341.                 if (Buffer == NIL)
  342.                     {
  343.                         goto SecondFailurePoint2;
  344.                     }
  345.                 if (!AddArrayToStack(ParamList,Buffer))
  346.                     {
  347.                         ReleasePtr(Buffer);
  348.                         goto SecondFailurePoint2;
  349.                     }
  350.             }
  351.          else
  352.             {
  353.                 char*                    Buffer;
  354.  
  355.                 Buffer = AllocPtrCanFail(0,"degeneratesample");
  356.                 if (Buffer == NIL)
  357.                     {
  358.                         goto SecondFailurePoint2;
  359.                     }
  360.                 if (!AddArrayToStack(ParamList,Buffer))
  361.                     {
  362.                         ReleasePtr(Buffer);
  363.                         goto SecondFailurePoint2;
  364.                     }
  365.             }
  366.  
  367.         /* executing the actual code */
  368.         OtherError = EvaluatePcode(ParamList,FuncCode,
  369.             AlgoSampObj->CodeCenter,&ErrorOpcode,&OffendingInstruction,AlgoSampObj->MainWindow,
  370.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleLeftCopy,
  371.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleRightCopy,
  372.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleMonoCopy,
  373.             (SampleErrors (*)(void*,char*,long*))&MainWindowGetWaveTableFrameCount,
  374.             (SampleErrors (*)(void*,char*,long*))&MainWindowGetWaveTableTableCount,
  375.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetWaveTableArray,
  376.             AlgoSampObj->MainWindow,
  377.             (struct InteractionWindowRec* (*)(void*))&MainWindowGetInteractionWindow);
  378.         DisposePcode(FuncCode);
  379.         if (OtherError != eEvalNoError)
  380.             {
  381.                 char*                    FuncNameString;
  382.                 FuncCodeRec*    ErrorFunction;
  383.                 MyBoolean            SuccessFlag;
  384.  
  385.                 /* present error message */
  386.                 AlgoSampObjectOpenWindow(AlgoSampObj);
  387.                 SuccessFlag = False;
  388.                 ErrorFunction = GetFunctionFromOpcode(AlgoSampObj->CodeCenter,ErrorOpcode);
  389.                 if (ErrorFunction == NIL)
  390.                     {
  391.                         FuncNameString = StringToBlockCopy("<anonymous>");
  392.                     }
  393.                  else
  394.                     {
  395.                         FuncNameString = CopyPtr(GetFunctionName(ErrorFunction));
  396.                     }
  397.                 if (FuncNameString != NIL)
  398.                     {
  399.                         char*                    Key;
  400.  
  401.                         Key = StringToBlockCopy("_");
  402.                         if (Key != NIL)
  403.                             {
  404.                                 char*                    BaseMessage;
  405.  
  406.                                 BaseMessage = StringFromRaw("Error in function _, instruction _:  _");
  407.                                 if (BaseMessage != NIL)
  408.                                     {
  409.                                         char*                    FixedMessage1;
  410.  
  411.                                         FixedMessage1 = ReplaceBlockCopy(BaseMessage,Key,FuncNameString);
  412.                                         if (FixedMessage1 != NIL)
  413.                                             {
  414.                                                 char*                    NumberStr;
  415.  
  416.                                                 NumberStr = IntegerToString(OffendingInstruction);
  417.                                                 if (NumberStr != NIL)
  418.                                                     {
  419.                                                         char*                    FixedMessage2;
  420.  
  421.                                                         FixedMessage2 = ReplaceBlockCopy(FixedMessage1,Key,NumberStr);
  422.                                                         if (FixedMessage2 != NIL)
  423.                                                             {
  424.                                                                 AlertHalt(FixedMessage2,GetPcodeErrorMessage(OtherError));
  425.                                                                 SuccessFlag = True;
  426.                                                                 ReleasePtr(FixedMessage2);
  427.                                                             }
  428.                                                         ReleasePtr(NumberStr);
  429.                                                     }
  430.                                                 ReleasePtr(FixedMessage1);
  431.                                             }
  432.                                         ReleasePtr(BaseMessage);
  433.                                     }
  434.                                 ReleasePtr(Key);
  435.                             }
  436.                         ReleasePtr(FuncNameString);
  437.                     }
  438.                 if (!SuccessFlag)
  439.                     {
  440.                         AlertHalt("There is not enough memory available to show the "
  441.                             "compile error message.",NIL);
  442.                     }
  443.                 DisposeParamStack(ParamList);
  444.                 return False;
  445.             }
  446.  
  447.         /* add the new data */
  448.         if (AlgoSampObjectGetNumChannels(AlgoSampObj) == eSampleStereo)
  449.             {
  450.                 largefixedsigned*                    Left;
  451.                 largefixedsigned*                    Right;
  452.                 long                                            Limit;
  453.                 long                                            Scan;
  454.  
  455.                 Left = (largefixedsigned*)GetStackArray(ParamList,10);
  456.                 Right = (largefixedsigned*)GetStackArray(ParamList,11);
  457.                 if ((Left == NIL) || (Right == NIL))
  458.                     {
  459.                         AlertHalt("NIL array returned from function building algorithmic sample.",NIL);
  460.                      StereoRebuildFailurePoint1:
  461.                         DisposeParamStack(ParamList);
  462.                         AlgoSampObjectOpenWindow(AlgoSampObj);
  463.                         return False;
  464.                     }
  465.                 if (PtrSize((char*)Left) != PtrSize((char*)Right))
  466.                     {
  467.                         AlertHalt("Left and Right algorithmic sample arrays are not the same size.",NIL);
  468.                      StereoRebuildFailurePoint2:
  469.                         goto StereoRebuildFailurePoint1;
  470.                     }
  471.                 ERROR(PtrSize((char*)Left) % sizeof(largefixedsigned) != 0,
  472.                     PRERR(ForceAbort,"AlgoSampObjectBuild:  array alignment error"));
  473.                 Limit = PtrSize((char*)Left) / sizeof(largefixedsigned);
  474.                 AlgoSampObj->SampleData = NewSampleStorageActual(AlgoSampObjectGetNumBits(
  475.                     AlgoSampObj),eSampleStereo,Limit);
  476.                 if (AlgoSampObj->SampleData == NIL)
  477.                     {
  478.                         AlertHalt("There is not enough memory available to build "
  479.                             "the algorithmic sample.",NIL);
  480.                      StereoRebuildFailurePoint3:
  481.                         goto StereoRebuildFailurePoint2;
  482.                     }
  483.                 for (Scan = 0; Scan < Limit; Scan += 1)
  484.                     {
  485.                         SetSampleStorageActualValue(AlgoSampObj->SampleData,Scan,
  486.                             eLeftChannel,Left[Scan]);
  487.                         SetSampleStorageActualValue(AlgoSampObj->SampleData,Scan,
  488.                             eRightChannel,Right[Scan]);
  489.                     }
  490.             }
  491.          else
  492.             {
  493.                 largefixedsigned*                    Middle;
  494.                 long                                            Limit;
  495.                 long                                            Scan;
  496.  
  497.                 Middle = (largefixedsigned*)GetStackArray(ParamList,10);
  498.                 if (Middle == NIL)
  499.                     {
  500.                         AlertHalt("NIL array returned from function building algorithmic sample.",NIL);
  501.                      MonoRebuildFailurePoint1:
  502.                         DisposeParamStack(ParamList);
  503.                         AlgoSampObjectOpenWindow(AlgoSampObj);
  504.                         return False;
  505.                     }
  506.                 ERROR(PtrSize((char*)Middle) % sizeof(largefixedsigned) != 0,
  507.                     PRERR(ForceAbort,"AlgoSampObjectBuild:  array alignment error"));
  508.                 Limit = PtrSize((char*)Middle) / sizeof(largefixedsigned);
  509.                 AlgoSampObj->SampleData = NewSampleStorageActual(AlgoSampObjectGetNumBits(
  510.                     AlgoSampObj),eSampleMono,Limit);
  511.                 if (AlgoSampObj->SampleData == NIL)
  512.                     {
  513.                         AlertHalt("There is not enough memory available to build "
  514.                             "the algorithmic sample.",NIL);
  515.                      MonoRebuildFailurePoint2:
  516.                         goto MonoRebuildFailurePoint1;
  517.                     }
  518.                 for (Scan = 0; Scan < Limit; Scan += 1)
  519.                     {
  520.                         SetSampleStorageActualValue(AlgoSampObj->SampleData,Scan,
  521.                             eMonoChannel,Middle[Scan]);
  522.                     }
  523.             }
  524.         DisposeParamStack(ParamList);
  525.         AlgoSampObj->NeedsToBeRebuilt = False;
  526.         return True;
  527.     }
  528.  
  529.  
  530. /* unconditionally unbuild the algorithmic sample */
  531. void                                    AlgoSampObjectUnbuild(AlgoSampObjectRec* AlgoSampObj)
  532.     {
  533.         CheckPtrExistence(AlgoSampObj);
  534.         if (AlgoSampObj->SampleData != NIL)
  535.             {
  536.                 DisposeSampleStorageActual(AlgoSampObj->SampleData);
  537.                 AlgoSampObj->SampleData = NIL;
  538.             }
  539.     }
  540.  
  541.  
  542. /* build the algorithmic sample if necessary.  return True if successful. */
  543. MyBoolean                            AlgoSampObjectMakeUpToDate(AlgoSampObjectRec* AlgoSampObj)
  544.     {
  545.         CheckPtrExistence(AlgoSampObj);
  546.         if ((AlgoSampObj->SampleData == NIL) || (AlgoSampObj->NeedsToBeRebuilt)
  547.             || (AlgoSampObj->AlgoSampWindow != NIL))
  548.             {
  549.                 return AlgoSampObjectBuild(AlgoSampObj);
  550.             }
  551.          else
  552.             {
  553.                 return True;
  554.             }
  555.     }
  556.  
  557.  
  558. /* get a copy of the algorithmic sample's name. */
  559. char*                                    AlgoSampObjectGetNameCopy(AlgoSampObjectRec* AlgoSampObj)
  560.     {
  561.         char*                                NameTemp;
  562.  
  563.         CheckPtrExistence(AlgoSampObj);
  564.         if (AlgoSampObj->AlgoSampWindow != NIL)
  565.             {
  566.                 NameTemp = AlgoSampWindowGetNameCopy(AlgoSampObj->AlgoSampWindow);
  567.             }
  568.          else
  569.             {
  570.                 NameTemp = CopyPtr(AlgoSampObj->Name);
  571.             }
  572.         if (NameTemp != NIL)
  573.             {
  574.                 SetTag(NameTemp,"AlgoSampNameCopy");
  575.             }
  576.         return NameTemp;
  577.     }
  578.  
  579.  
  580. /* set the algorithmic sample's name.  the object becomes the owner of the Name */
  581. /* block so the caller should not release it. */
  582. void                                    AlgoSampObjectNewName(AlgoSampObjectRec* AlgoSampObj, char* Name)
  583.     {
  584.         CheckPtrExistence(AlgoSampObj);
  585.         CheckPtrExistence(Name);
  586.         ReleasePtr(AlgoSampObj->Name);
  587.         SetTag(Name,"AlgoSampName");
  588.         AlgoSampObj->Name = Name;
  589.         AlgoSampObj->DataModified = True;
  590.         AlgoSampObj->NeedsToBeRebuilt = True;
  591.         AlgoSampListAlgoSampNameChanged(AlgoSampObj->AlgoSampList,AlgoSampObj);
  592.     }
  593.  
  594.  
  595. /* get a copy of the formula that generates the algorithmic sample */
  596. char*                                    AlgoSampObjectGetFormulaCopy(AlgoSampObjectRec* AlgoSampObj)
  597.     {
  598.         char*                                TextCopy;
  599.  
  600.         CheckPtrExistence(AlgoSampObj);
  601.         if (AlgoSampObj->AlgoSampWindow != NIL)
  602.             {
  603.                 TextCopy = AlgoSampWindowGetFormulaCopy(AlgoSampObj->AlgoSampWindow);
  604.             }
  605.          else
  606.             {
  607.                 TextCopy = CopyPtr(AlgoSampObj->AlgoSampFormula);
  608.             }
  609.         if (TextCopy != NIL)
  610.             {
  611.                 SetTag(TextCopy,"AlgoSampFormulaCopy");
  612.             }
  613.         return TextCopy;
  614.     }
  615.  
  616.  
  617. /* install a new formula into the algorithmic sample.  the object becomes the owner */
  618. /* of the formula, so the caller should not release it */
  619. void                                    AlgoSampObjectNewFormula(AlgoSampObjectRec* AlgoSampObj,
  620.                                                 char* Formula)
  621.     {
  622.         CheckPtrExistence(AlgoSampObj);
  623.         CheckPtrExistence(Formula);
  624.         ReleasePtr(AlgoSampObj->AlgoSampFormula);
  625.         SetTag(Formula,"AlgoSampFormula");
  626.         AlgoSampObj->AlgoSampFormula = Formula;
  627.         AlgoSampObj->DataModified = True;
  628.         AlgoSampObj->NeedsToBeRebuilt = True;
  629.     }
  630.  
  631.  
  632. /* get the number of bits in a channel for the algorithmic sample */
  633. NumBitsType                        AlgoSampObjectGetNumBits(AlgoSampObjectRec* AlgoSampObj)
  634.     {
  635.         CheckPtrExistence(AlgoSampObj);
  636.         if (AlgoSampObj->AlgoSampWindow != NIL)
  637.             {
  638.                 return AlgoSampWindowGetNumBits(AlgoSampObj->AlgoSampWindow);
  639.             }
  640.          else
  641.             {
  642.                 return AlgoSampObj->NumBits;
  643.             }
  644.     }
  645.  
  646.  
  647. /* change the number of bits in a channel for the algorithmic sample */
  648. void                                    AlgoSampObjectPutNumBits(AlgoSampObjectRec* AlgoSampObj,
  649.                                                 NumBitsType NewNumBits)
  650.     {
  651.         CheckPtrExistence(AlgoSampObj);
  652.         AlgoSampObjectUnbuild(AlgoSampObj);
  653.         ERROR((NewNumBits != eSample16bit) && (NewNumBits != eSample8bit),
  654.             PRERR(ForceAbort,"AlgoSampObjectPutNumBits:  bad value"));
  655.         AlgoSampObj->NumBits = NewNumBits;
  656.         AlgoSampObj->DataModified = True;
  657.         AlgoSampObj->NeedsToBeRebuilt = True;
  658.     }
  659.  
  660.  
  661. /* get the number of channels in the algorithmic sample */
  662. NumChannelsType                AlgoSampObjectGetNumChannels(AlgoSampObjectRec* AlgoSampObj)
  663.     {
  664.         CheckPtrExistence(AlgoSampObj);
  665.         if (AlgoSampObj->AlgoSampWindow != NIL)
  666.             {
  667.                 return AlgoSampWindowGetNumChannels(AlgoSampObj->AlgoSampWindow);
  668.             }
  669.          else
  670.             {
  671.                 return AlgoSampObj->NumChannels;
  672.             }
  673.     }
  674.  
  675.  
  676. /* change the number of channels for the algorithmic sample */
  677. void                                    AlgoSampObjectPutNumChannels(AlgoSampObjectRec* AlgoSampObj,
  678.                                                 NumChannelsType NewNumChannels)
  679.     {
  680.         CheckPtrExistence(AlgoSampObj);
  681.         AlgoSampObjectUnbuild(AlgoSampObj);
  682.         ERROR((NewNumChannels != eSampleMono) && (NewNumChannels != eSampleStereo),
  683.             PRERR(ForceAbort,"AlgoSampObjectPutNumChannels:  bad value"));
  684.         AlgoSampObj->NumChannels = NewNumChannels;
  685.         AlgoSampObj->DataModified = True;
  686.         AlgoSampObj->NeedsToBeRebuilt = True;
  687.     }
  688.  
  689.  
  690. /* get the number of data frames in the algorithmic sample */
  691. long                                    AlgoSampObjetGetNumFrames(AlgoSampObjectRec* AlgoSampObj)
  692.     {
  693.         CheckPtrExistence(AlgoSampObj);
  694.         ERROR(AlgoSampObj->SampleData == NIL,PRERR(ForceAbort,
  695.             "AlgoSampObjetGetNumFrames:  sample data has not been built"));
  696.         return GetSampleStorageActualNumFrames(AlgoSampObj->SampleData);
  697.     }
  698.  
  699.  
  700. long                                    AlgoSampObjectGetOrigin(AlgoSampObjectRec* AlgoSampObj)
  701.     {
  702.         CheckPtrExistence(AlgoSampObj);
  703.         if (AlgoSampObj->AlgoSampWindow != NIL)
  704.             {
  705.                 return AlgoSampWindowGetOrigin(AlgoSampObj->AlgoSampWindow);
  706.             }
  707.          else
  708.             {
  709.                 return AlgoSampObj->Origin;
  710.             }
  711.     }
  712.  
  713.  
  714. long                                    AlgoSampObjectGetLoopStart1(AlgoSampObjectRec* AlgoSampObj)
  715.     {
  716.         CheckPtrExistence(AlgoSampObj);
  717.         if (AlgoSampObj->AlgoSampWindow != NIL)
  718.             {
  719.                 return AlgoSampWindowGetLoopStart1(AlgoSampObj->AlgoSampWindow);
  720.             }
  721.          else
  722.             {
  723.                 return AlgoSampObj->LoopStart1;
  724.             }
  725.     }
  726.  
  727.  
  728. long                                    AlgoSampObjectGetLoopStart2(AlgoSampObjectRec* AlgoSampObj)
  729.     {
  730.         CheckPtrExistence(AlgoSampObj);
  731.         if (AlgoSampObj->AlgoSampWindow != NIL)
  732.             {
  733.                 return AlgoSampWindowGetLoopStart2(AlgoSampObj->AlgoSampWindow);
  734.             }
  735.          else
  736.             {
  737.                 return AlgoSampObj->LoopStart2;
  738.             }
  739.     }
  740.  
  741.  
  742. long                                    AlgoSampObjectGetLoopStart3(AlgoSampObjectRec* AlgoSampObj)
  743.     {
  744.         CheckPtrExistence(AlgoSampObj);
  745.         if (AlgoSampObj->AlgoSampWindow != NIL)
  746.             {
  747.                 return AlgoSampWindowGetLoopStart3(AlgoSampObj->AlgoSampWindow);
  748.             }
  749.          else
  750.             {
  751.                 return AlgoSampObj->LoopStart3;
  752.             }
  753.     }
  754.  
  755.  
  756. long                                    AlgoSampObjectGetLoopEnd1(AlgoSampObjectRec* AlgoSampObj)
  757.     {
  758.         CheckPtrExistence(AlgoSampObj);
  759.         if (AlgoSampObj->AlgoSampWindow != NIL)
  760.             {
  761.                 return AlgoSampWindowGetLoopEnd1(AlgoSampObj->AlgoSampWindow);
  762.             }
  763.          else
  764.             {
  765.                 return AlgoSampObj->LoopEnd1;
  766.             }
  767.     }
  768.  
  769.  
  770. long                                    AlgoSampObjectGetLoopEnd2(AlgoSampObjectRec* AlgoSampObj)
  771.     {
  772.         CheckPtrExistence(AlgoSampObj);
  773.         if (AlgoSampObj->AlgoSampWindow != NIL)
  774.             {
  775.                 return AlgoSampWindowGetLoopEnd2(AlgoSampObj->AlgoSampWindow);
  776.             }
  777.          else
  778.             {
  779.                 return AlgoSampObj->LoopEnd2;
  780.             }
  781.     }
  782.  
  783.  
  784. long                                    AlgoSampObjectGetLoopEnd3(AlgoSampObjectRec* AlgoSampObj)
  785.     {
  786.         CheckPtrExistence(AlgoSampObj);
  787.         if (AlgoSampObj->AlgoSampWindow != NIL)
  788.             {
  789.                 return AlgoSampWindowGetLoopEnd3(AlgoSampObj->AlgoSampWindow);
  790.             }
  791.          else
  792.             {
  793.                 return AlgoSampObj->LoopEnd3;
  794.             }
  795.     }
  796.  
  797.  
  798. long                                    AlgoSampObjectGetSamplingRate(AlgoSampObjectRec* AlgoSampObj)
  799.     {
  800.         CheckPtrExistence(AlgoSampObj);
  801.         if (AlgoSampObj->AlgoSampWindow != NIL)
  802.             {
  803.                 return AlgoSampWindowGetSamplingRate(AlgoSampObj->AlgoSampWindow);
  804.             }
  805.          else
  806.             {
  807.                 return AlgoSampObj->SamplingRate;
  808.             }
  809.     }
  810.  
  811.  
  812. double                                AlgoSampObjectGetNaturalFrequency(AlgoSampObjectRec* AlgoSampObj)
  813.     {
  814.         CheckPtrExistence(AlgoSampObj);
  815.         if (AlgoSampObj->AlgoSampWindow != NIL)
  816.             {
  817.                 return AlgoSampWindowGetNaturalFrequency(AlgoSampObj->AlgoSampWindow);
  818.             }
  819.          else
  820.             {
  821.                 return AlgoSampObj->NaturalFrequency;
  822.             }
  823.     }
  824.  
  825.  
  826. char*                                    AlgoSampObjectGetRawData(AlgoSampObjectRec* AlgoSampObj)
  827.     {
  828.         CheckPtrExistence(AlgoSampObj);
  829.         if ((AlgoSampObj->SampleData == NIL) || AlgoSampObj->NeedsToBeRebuilt)
  830.             {
  831.                 return NIL;
  832.             }
  833.         return GetSampleStorageActualRawData(AlgoSampObj->SampleData);
  834.     }
  835.  
  836.  
  837. void                                    AlgoSampObjectPutOrigin(AlgoSampObjectRec* AlgoSampObj,
  838.                                                 long Origin)
  839.     {
  840.         CheckPtrExistence(AlgoSampObj);
  841.         AlgoSampObj->Origin = Origin;
  842.         AlgoSampObj->DataModified = True;
  843.         AlgoSampObj->NeedsToBeRebuilt = True;
  844.     }
  845.  
  846.  
  847. void                                    AlgoSampObjectPutLoopStart1(AlgoSampObjectRec* AlgoSampObj,
  848.                                                 long LoopStart)
  849.     {
  850.         CheckPtrExistence(AlgoSampObj);
  851.         AlgoSampObj->LoopStart1 = LoopStart;
  852.         AlgoSampObj->DataModified = True;
  853.         AlgoSampObj->NeedsToBeRebuilt = True;
  854.     }
  855.  
  856.  
  857. void                                    AlgoSampObjectPutLoopStart2(AlgoSampObjectRec* AlgoSampObj,
  858.                                                 long LoopStart)
  859.     {
  860.         CheckPtrExistence(AlgoSampObj);
  861.         AlgoSampObj->LoopStart2 = LoopStart;
  862.         AlgoSampObj->DataModified = True;
  863.         AlgoSampObj->NeedsToBeRebuilt = True;
  864.     }
  865.  
  866.  
  867. void                                    AlgoSampObjectPutLoopStart3(AlgoSampObjectRec* AlgoSampObj,
  868.                                                 long LoopStart)
  869.     {
  870.         CheckPtrExistence(AlgoSampObj);
  871.         AlgoSampObj->LoopStart3 = LoopStart;
  872.         AlgoSampObj->DataModified = True;
  873.         AlgoSampObj->NeedsToBeRebuilt = True;
  874.     }
  875.  
  876.  
  877. void                                    AlgoSampObjectPutLoopEnd1(AlgoSampObjectRec* AlgoSampObj,
  878.                                                 long LoopEnd)
  879.     {
  880.         CheckPtrExistence(AlgoSampObj);
  881.         AlgoSampObj->LoopEnd1 = LoopEnd;
  882.         AlgoSampObj->DataModified = True;
  883.         AlgoSampObj->NeedsToBeRebuilt = True;
  884.     }
  885.  
  886.  
  887. void                                    AlgoSampObjectPutLoopEnd2(AlgoSampObjectRec* AlgoSampObj,
  888.                                                 long LoopEnd)
  889.     {
  890.         CheckPtrExistence(AlgoSampObj);
  891.         AlgoSampObj->LoopEnd2 = LoopEnd;
  892.         AlgoSampObj->DataModified = True;
  893.         AlgoSampObj->NeedsToBeRebuilt = True;
  894.     }
  895.  
  896.  
  897. void                                    AlgoSampObjectPutLoopEnd3(AlgoSampObjectRec* AlgoSampObj,
  898.                                                 long LoopEnd)
  899.     {
  900.         CheckPtrExistence(AlgoSampObj);
  901.         AlgoSampObj->LoopEnd3 = LoopEnd;
  902.         AlgoSampObj->DataModified = True;
  903.         AlgoSampObj->NeedsToBeRebuilt = True;
  904.     }
  905.  
  906.  
  907. void                                    AlgoSampObjectPutSamplingRate(AlgoSampObjectRec* AlgoSampObj,
  908.                                                 long SamplingRate)
  909.     {
  910.         CheckPtrExistence(AlgoSampObj);
  911.         if (SamplingRate < MINSAMPLINGRATE)
  912.             {
  913.                 SamplingRate = MINSAMPLINGRATE;
  914.             }
  915.         if (SamplingRate > MAXSAMPLINGRATE)
  916.             {
  917.                 SamplingRate = MAXSAMPLINGRATE;
  918.             }
  919.         AlgoSampObj->SamplingRate = SamplingRate;
  920.         AlgoSampObj->DataModified = True;
  921.         AlgoSampObj->NeedsToBeRebuilt = True;
  922.     }
  923.  
  924.  
  925. void                                    AlgoSampObjectPutNaturalFrequency(AlgoSampObjectRec* AlgoSampObj,
  926.                                                 double NaturalFrequency)
  927.     {
  928.         CheckPtrExistence(AlgoSampObj);
  929.         if (NaturalFrequency < MINNATURALFREQ)
  930.             {
  931.                 NaturalFrequency = MINNATURALFREQ;
  932.             }
  933.         if (NaturalFrequency > MAXNATURALFREQ)
  934.             {
  935.                 NaturalFrequency = MAXNATURALFREQ;
  936.             }
  937.         AlgoSampObj->NaturalFrequency = NaturalFrequency;
  938.         AlgoSampObj->DataModified = True;
  939.         AlgoSampObj->NeedsToBeRebuilt = True;
  940.     }
  941.  
  942.  
  943. /* call which makes object open its editor window */
  944. MyBoolean                            AlgoSampObjectOpenWindow(AlgoSampObjectRec* AlgoSampObj)
  945.     {
  946.         CheckPtrExistence(AlgoSampObj);
  947.         if (AlgoSampObj->AlgoSampWindow == NIL)
  948.             {
  949.                 AlgoSampObj->AlgoSampWindow = NewAlgoSampWindow(AlgoSampObj->MainWindow,
  950.                     AlgoSampObj,AlgoSampObj->AlgoSampList,AlgoSampObj->SavedWindowXLoc,
  951.                     AlgoSampObj->SavedWindowYLoc,AlgoSampObj->SavedWindowWidth,
  952.                     AlgoSampObj->SavedWindowHeight);
  953.             }
  954.          else
  955.             {
  956.                 AlgoSampWindowBringToTop(AlgoSampObj->AlgoSampWindow);
  957.             }
  958.         return (AlgoSampObj->AlgoSampWindow != NIL);
  959.     }
  960.  
  961.  
  962. /* this is called by the window when it is closing to notify the object. */
  963. /* the object should not take any action. */
  964. void                                    AlgoSampObjectClosingWindowNotify(AlgoSampObjectRec* AlgoSampObj,
  965.                                                 short NewX, short NewY, short NewWidth, short NewHeight)
  966.     {
  967.         CheckPtrExistence(AlgoSampObj);
  968.         ERROR(AlgoSampObj->AlgoSampWindow == NIL,PRERR(ForceAbort,
  969.             "AlgoSampObjectClosingWindowNotify:  window not open"));
  970.         AlgoSampObj->AlgoSampWindow = NIL;
  971.         AlgoSampObj->SavedWindowXLoc = NewX;
  972.         AlgoSampObj->SavedWindowYLoc = NewY;
  973.         AlgoSampObj->SavedWindowWidth = NewWidth;
  974.         AlgoSampObj->SavedWindowHeight = NewHeight;
  975.     }
  976.  
  977.  
  978. /* the document's name has changed, so the windows need to be updated */
  979. void                                    AlgoSampObjectGlobalNameChange(AlgoSampObjectRec* AlgoSampObj,
  980.                                                 char* NewFilename)
  981.     {
  982.         CheckPtrExistence(AlgoSampObj);
  983.         if (AlgoSampObj->AlgoSampWindow != NIL)
  984.             {
  985.                 AlgoSampWindowGlobalNameChange(AlgoSampObj->AlgoSampWindow,NewFilename);
  986.             }
  987.     }
  988.  
  989.  
  990. /* Algorithmic Sample Object Subblock Format: */
  991. /*   1-byte format version number */
  992. /*       should be 1 */
  993. /*   2-bytes little endian window X location (signed, origin at top-left corner) */
  994. /*   2-bytes little endian window Y location */
  995. /*   2-bytes little endian window width */
  996. /*   2-bytes little endian window height */
  997. /*   4-bytes little endian name length descriptor */
  998. /*   n-bytes name string (line feed = 0x0a) */
  999. /*   4-bytes little endian formula length descriptor */
  1000. /*   n-bytes formula string (line feed = 0x0a) */
  1001. /*   1-byte number of bits */
  1002. /*       should be 8 or 16 */
  1003. /*   1-byte number of channels */
  1004. /*       1 = mono */
  1005. /*       2 = stereo */
  1006. /*   4-bytes little endian sample origin */
  1007. /*   4-bytes little endian loop 1 start point */
  1008. /*   4-bytes little endian loop 1 end point */
  1009. /*   4-bytes little endian loop 2 start point */
  1010. /*   4-bytes little endian loop 2 end point */
  1011. /*   4-bytes little endian loop 3 start point */
  1012. /*   4-bytes little endian loop 3 end point */
  1013. /*   4-bytes little endian sampling rate */
  1014. /*       should be between 100 and 65535 */
  1015. /*   4-byte little endian natural frequency fractional portion */
  1016. /*       unsigned; divide by 2^32 to get the actual fraction */
  1017. /*   4-byte little endian natural frequency integer portion */
  1018. /*       total natural frequency should be between 0.01 and 1e6 */
  1019.  
  1020.  
  1021. /* read from the file and create a new algorithmic sample object from it. */
  1022. FileLoadingErrors            AlgoSampObjectNewFromFile(AlgoSampObjectRec** ObjectOut,
  1023.                                                 struct BufferedInputRec* Input, struct CodeCenterRec* CodeCenter,
  1024.                                                 struct MainWindowRec* MainWindow,
  1025.                                                 struct AlgoSampListRec* AlgoSampList)
  1026.     {
  1027.         unsigned char                UnsignedChar;
  1028.         signed short                SignedShort;
  1029.         AlgoSampObjectRec*    AlgoSampObj;
  1030.         FileLoadingErrors        Error;
  1031.         signed long                    SignedLong;
  1032.         unsigned long                UnsignedLong;
  1033.  
  1034.         CheckPtrExistence(Input);
  1035.         CheckPtrExistence(CodeCenter);
  1036.         CheckPtrExistence(MainWindow);
  1037.         CheckPtrExistence(AlgoSampList);
  1038.  
  1039.         AlgoSampObj = (AlgoSampObjectRec*)AllocPtrCanFail(sizeof(AlgoSampObjectRec),
  1040.             "AlgoSampObjectRec");
  1041.         if (AlgoSampObj == NIL)
  1042.             {
  1043.                 Error = eFileLoadOutOfMemory;
  1044.              FailurePoint1:
  1045.                 return Error;
  1046.             }
  1047.  
  1048.         /*   1-byte format version number */
  1049.         /*       should be 1 */
  1050.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  1051.             {
  1052.                 Error = eFileLoadDiskError;
  1053.              FailurePoint2:
  1054.                 ReleasePtr((char*)AlgoSampObj);
  1055.                 goto FailurePoint1;
  1056.             }
  1057.  
  1058.         /*   2-bytes little endian window X location (signed, origin at top-left corner) */
  1059.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  1060.             {
  1061.                 Error = eFileLoadDiskError;
  1062.              FailurePoint3:
  1063.                 goto FailurePoint2;
  1064.             }
  1065.         AlgoSampObj->SavedWindowXLoc = SignedShort;
  1066.  
  1067.         /*   2-bytes little endian window Y location */
  1068.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  1069.             {
  1070.                 Error = eFileLoadDiskError;
  1071.              FailurePoint4:
  1072.                 goto FailurePoint3;
  1073.             }
  1074.         AlgoSampObj->SavedWindowYLoc = SignedShort;
  1075.  
  1076.         /*   2-bytes little endian window width */
  1077.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  1078.             {
  1079.                 Error = eFileLoadDiskError;
  1080.              FailurePoint5:
  1081.                 goto FailurePoint4;
  1082.             }
  1083.         AlgoSampObj->SavedWindowWidth = SignedShort;
  1084.  
  1085.         /*   2-bytes little endian window height */
  1086.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  1087.             {
  1088.                 Error = eFileLoadDiskError;
  1089.              FailurePoint6:
  1090.                 goto FailurePoint5;
  1091.             }
  1092.         AlgoSampObj->SavedWindowHeight = SignedShort;
  1093.  
  1094.         /*   4-bytes little endian name length descriptor */
  1095.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1096.             {
  1097.                 Error = eFileLoadDiskError;
  1098.              FailurePoint7:
  1099.                 goto FailurePoint6;
  1100.             }
  1101.         if (SignedLong < 0)
  1102.             {
  1103.                 Error = eFileLoadBadFormat;
  1104.              FailurePoint8:
  1105.                 goto FailurePoint7;
  1106.             }
  1107.  
  1108.         /*   n-bytes name string (line feed = 0x0a) */
  1109.         AlgoSampObj->Name = AllocPtrCanFail(SignedLong,"AlgoSampObjectRec:  name");
  1110.         if (AlgoSampObj->Name == NIL)
  1111.             {
  1112.                 Error = eFileLoadOutOfMemory;
  1113.              FailurePoint9:
  1114.                 goto FailurePoint8;
  1115.             }
  1116.         if (!ReadBufferedInput(Input,SignedLong,AlgoSampObj->Name))
  1117.             {
  1118.                 Error = eFileLoadDiskError;
  1119.              FailurePoint10:
  1120.                 ReleasePtr(AlgoSampObj->Name);
  1121.                 goto FailurePoint9;
  1122.             }
  1123.  
  1124.         /*   4-bytes little endian formula length descriptor */
  1125.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1126.             {
  1127.                 Error = eFileLoadDiskError;
  1128.              FailurePoint11:
  1129.                 goto FailurePoint10;
  1130.             }
  1131.         if (SignedLong < 0)
  1132.             {
  1133.                 Error = eFileLoadBadFormat;
  1134.              FailurePoint12:
  1135.                 goto FailurePoint11;
  1136.             }
  1137.  
  1138.         /*   n-bytes formula string (line feed = 0x0a) */
  1139.         AlgoSampObj->AlgoSampFormula = AllocPtrCanFail(SignedLong,
  1140.             "AlgoSampObjectRec:  formula");
  1141.         if (AlgoSampObj->AlgoSampFormula == NIL)
  1142.             {
  1143.                 Error = eFileLoadOutOfMemory;
  1144.              FailurePoint13:
  1145.                 goto FailurePoint12;
  1146.             }
  1147.         if (!ReadBufferedInput(Input,SignedLong,AlgoSampObj->AlgoSampFormula))
  1148.             {
  1149.                 Error = eFileLoadDiskError;
  1150.              FailurePoint14:
  1151.                 ReleasePtr(AlgoSampObj->AlgoSampFormula);
  1152.                 goto FailurePoint13;
  1153.             }
  1154.  
  1155.         /*   1-byte number of bits */
  1156.         /*       should be 8 or 16 */
  1157.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  1158.             {
  1159.                 Error = eFileLoadDiskError;
  1160.              FailurePoint15:
  1161.                 goto FailurePoint14;
  1162.             }
  1163.         if (UnsignedChar == 8)
  1164.             {
  1165.                 AlgoSampObj->NumBits = eSample8bit;
  1166.             }
  1167.         else if (UnsignedChar == 16)
  1168.             {
  1169.                 AlgoSampObj->NumBits = eSample16bit;
  1170.             }
  1171.         else
  1172.             {
  1173.                 Error = eFileLoadBadFormat;
  1174.              FailurePoint16:
  1175.                 goto FailurePoint15;
  1176.             }
  1177.  
  1178.         /*   1-byte number of channels */
  1179.         /*       1 = mono */
  1180.         /*       2 = stereo */
  1181.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  1182.             {
  1183.                 Error = eFileLoadDiskError;
  1184.              FailurePoint17:
  1185.                 goto FailurePoint16;
  1186.             }
  1187.         if (UnsignedChar == 1)
  1188.             {
  1189.                 AlgoSampObj->NumChannels = eSampleMono;
  1190.             }
  1191.         else if (UnsignedChar == 2)
  1192.             {
  1193.                 AlgoSampObj->NumChannels = eSampleStereo;
  1194.             }
  1195.         else
  1196.             {
  1197.                 Error = eFileLoadBadFormat;
  1198.              FailurePoint18:
  1199.                 goto FailurePoint17;
  1200.             }
  1201.  
  1202.         /*   4-bytes little endian sample origin */
  1203.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1204.             {
  1205.                 Error = eFileLoadDiskError;
  1206.              FailurePoint19:
  1207.                 goto FailurePoint18;
  1208.             }
  1209.         AlgoSampObj->Origin = SignedLong;
  1210.  
  1211.         /*   4-bytes little endian loop 1 start point */
  1212.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1213.             {
  1214.                 Error = eFileLoadDiskError;
  1215.              FailurePoint20:
  1216.                 goto FailurePoint19;
  1217.             }
  1218.         AlgoSampObj->LoopStart1 = SignedLong;
  1219.  
  1220.         /*   4-bytes little endian loop 1 end point */
  1221.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1222.             {
  1223.                 Error = eFileLoadDiskError;
  1224.              FailurePoint21:
  1225.                 goto FailurePoint20;
  1226.             }
  1227.         AlgoSampObj->LoopEnd1 = SignedLong;
  1228.  
  1229.         /*   4-bytes little endian loop 2 start point */
  1230.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1231.             {
  1232.                 Error = eFileLoadDiskError;
  1233.              FailurePoint22:
  1234.                 goto FailurePoint21;
  1235.             }
  1236.         AlgoSampObj->LoopStart2 = SignedLong;
  1237.  
  1238.         /*   4-bytes little endian loop 2 end point */
  1239.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1240.             {
  1241.                 Error = eFileLoadDiskError;
  1242.              FailurePoint23:
  1243.                 goto FailurePoint22;
  1244.             }
  1245.         AlgoSampObj->LoopEnd2 = SignedLong;
  1246.  
  1247.         /*   4-bytes little endian loop 3 start point */
  1248.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1249.             {
  1250.                 Error = eFileLoadDiskError;
  1251.              FailurePoint24:
  1252.                 goto FailurePoint23;
  1253.             }
  1254.         AlgoSampObj->LoopStart3 = SignedLong;
  1255.  
  1256.         /*   4-bytes little endian loop 3 end point */
  1257.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1258.             {
  1259.                 Error = eFileLoadDiskError;
  1260.              FailurePoint25:
  1261.                 goto FailurePoint24;
  1262.             }
  1263.         AlgoSampObj->LoopEnd3 = SignedLong;
  1264.  
  1265.         /*   4-bytes little endian sampling rate */
  1266.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1267.             {
  1268.                 Error = eFileLoadDiskError;
  1269.              FailurePoint26:
  1270.                 goto FailurePoint25;
  1271.             }
  1272.         if (SignedLong < MINSAMPLINGRATE)
  1273.             {
  1274.                 SignedLong = MINSAMPLINGRATE;
  1275.             }
  1276.         if (SignedLong > MAXSAMPLINGRATE)
  1277.             {
  1278.                 SignedLong = MAXSAMPLINGRATE;
  1279.             }
  1280.         AlgoSampObj->SamplingRate = SignedLong;
  1281.  
  1282.         /*   4-byte little endian natural frequency fractional portion */
  1283.         /*       unsigned; divide by 2^32 to get the actual fraction */
  1284.         if (!ReadBufferedUnsignedLongLittleEndian(Input,&UnsignedLong))
  1285.             {
  1286.                 Error = eFileLoadDiskError;
  1287.              FailurePoint27:
  1288.                 goto FailurePoint26;
  1289.             }
  1290.         AlgoSampObj->NaturalFrequency = (double)UnsignedLong / 4294967296.0L;
  1291.  
  1292.         /*   4-byte little endian natural frequency integer portion */
  1293.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1294.             {
  1295.                 Error = eFileLoadDiskError;
  1296.              FailurePoint28:
  1297.                 goto FailurePoint27;
  1298.             }
  1299.         AlgoSampObj->NaturalFrequency += SignedLong;
  1300.         if (AlgoSampObj->NaturalFrequency < MINNATURALFREQ)
  1301.             {
  1302.                 AlgoSampObj->NaturalFrequency = MINNATURALFREQ;
  1303.             }
  1304.         if (AlgoSampObj->NaturalFrequency > MAXNATURALFREQ)
  1305.             {
  1306.                 AlgoSampObj->NaturalFrequency = MAXNATURALFREQ;
  1307.             }
  1308.  
  1309.         /* fill in the other fields */
  1310.         AlgoSampObj->DataModified = False;
  1311.         AlgoSampObj->NeedsToBeRebuilt = True;
  1312.         AlgoSampObj->SampleData = NIL;
  1313.         AlgoSampObj->AlgoSampWindow = NIL;
  1314.         AlgoSampObj->CodeCenter = CodeCenter;
  1315.         AlgoSampObj->MainWindow = MainWindow;
  1316.         AlgoSampObj->AlgoSampList = AlgoSampList;
  1317.  
  1318.         *ObjectOut = AlgoSampObj;
  1319.         return eFileLoadNoError;
  1320.     }
  1321.  
  1322.  
  1323. /* write the object out to the specified file. */
  1324. FileLoadingErrors            AlgoSampObjectWriteOutData(AlgoSampObjectRec* AlgoSampObj,
  1325.                                                 struct BufferedOutputRec* Output)
  1326.     {
  1327.         char*                                StringTemp;
  1328.         double                            NaturalFreqTemp;
  1329.  
  1330.         CheckPtrExistence(AlgoSampObj);
  1331.         CheckPtrExistence(Output);
  1332.  
  1333.         /*   1-byte format version number */
  1334.         /*       should be 1 */
  1335.         if (!WriteBufferedUnsignedChar(Output,1))
  1336.             {
  1337.                 return eFileLoadDiskError;
  1338.             }
  1339.  
  1340.         /*   2-bytes little endian window X location (signed, origin at top-left corner) */
  1341.         /* if the window is open when we save, the most recent coordinates of the */
  1342.         /* window will not be used */
  1343.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoSampObj->SavedWindowXLoc))
  1344.             {
  1345.                 return eFileLoadDiskError;
  1346.             }
  1347.  
  1348.         /*   2-bytes little endian window Y location */
  1349.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoSampObj->SavedWindowYLoc))
  1350.             {
  1351.                 return eFileLoadDiskError;
  1352.             }
  1353.  
  1354.         /*   2-bytes little endian window width */
  1355.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoSampObj->SavedWindowWidth))
  1356.             {
  1357.                 return eFileLoadDiskError;
  1358.             }
  1359.  
  1360.         /*   2-bytes little endian window height */
  1361.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoSampObj->SavedWindowHeight))
  1362.             {
  1363.                 return eFileLoadDiskError;
  1364.             }
  1365.  
  1366.         /*   4-bytes little endian name length descriptor */
  1367.         StringTemp = AlgoSampObjectGetNameCopy(AlgoSampObj);
  1368.         if (StringTemp == NIL)
  1369.             {
  1370.                 return eFileLoadOutOfMemory;
  1371.             }
  1372.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  1373.             {
  1374.                 ReleasePtr(StringTemp);
  1375.                 return eFileLoadDiskError;
  1376.             }
  1377.  
  1378.         /*   n-bytes name string (line feed = 0x0a) */
  1379.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  1380.             {
  1381.                 ReleasePtr(StringTemp);
  1382.                 return eFileLoadDiskError;
  1383.             }
  1384.         ReleasePtr(StringTemp);
  1385.  
  1386.         /*   4-bytes little endian formula length descriptor */
  1387.         StringTemp = AlgoSampObjectGetFormulaCopy(AlgoSampObj);
  1388.         if (StringTemp == NIL)
  1389.             {
  1390.                 return eFileLoadOutOfMemory;
  1391.             }
  1392.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  1393.             {
  1394.                 ReleasePtr(StringTemp);
  1395.                 return eFileLoadDiskError;
  1396.             }
  1397.  
  1398.         /*   n-bytes formula string (line feed = 0x0a) */
  1399.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  1400.             {
  1401.                 ReleasePtr(StringTemp);
  1402.                 return eFileLoadDiskError;
  1403.             }
  1404.         ReleasePtr(StringTemp);
  1405.  
  1406.         /*   1-byte number of bits */
  1407.         /*       should be 8 or 16 */
  1408.         switch (AlgoSampObjectGetNumBits(AlgoSampObj))
  1409.             {
  1410.                 default:
  1411.                     EXECUTE(PRERR(ForceAbort,"AlgoSampObjectWriteOutData:  bad num bits"));
  1412.                     break;
  1413.                 case eSample8bit:
  1414.                     if (!WriteBufferedUnsignedChar(Output,8))
  1415.                         {
  1416.                             return eFileLoadDiskError;
  1417.                         }
  1418.                     break;
  1419.                 case eSample16bit:
  1420.                     if (!WriteBufferedUnsignedChar(Output,16))
  1421.                         {
  1422.                             return eFileLoadDiskError;
  1423.                         }
  1424.                     break;
  1425.             }
  1426.  
  1427.         /*   1-byte number of channels */
  1428.         /*       1 = mono */
  1429.         /*       2 = stereo */
  1430.         switch (AlgoSampObjectGetNumChannels(AlgoSampObj))
  1431.             {
  1432.                 default:
  1433.                     EXECUTE(PRERR(ForceAbort,"AlgoSampObjectWriteOutData:  bad num channels"));
  1434.                     break;
  1435.                 case eSampleMono:
  1436.                     if (!WriteBufferedUnsignedChar(Output,1))
  1437.                         {
  1438.                             return eFileLoadDiskError;
  1439.                         }
  1440.                     break;
  1441.                 case eSampleStereo:
  1442.                     if (!WriteBufferedUnsignedChar(Output,2))
  1443.                         {
  1444.                             return eFileLoadDiskError;
  1445.                         }
  1446.                     break;
  1447.             }
  1448.  
  1449.         /*   4-bytes little endian sample origin */
  1450.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1451.             AlgoSampObjectGetOrigin(AlgoSampObj)))
  1452.             {
  1453.                 return eFileLoadDiskError;
  1454.             }
  1455.  
  1456.         /*   4-bytes little endian loop 1 start point */
  1457.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1458.             AlgoSampObjectGetLoopStart1(AlgoSampObj)))
  1459.             {
  1460.                 return eFileLoadDiskError;
  1461.             }
  1462.  
  1463.         /*   4-bytes little endian loop 1 end point */
  1464.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1465.             AlgoSampObjectGetLoopEnd1(AlgoSampObj)))
  1466.             {
  1467.                 return eFileLoadDiskError;
  1468.             }
  1469.  
  1470.         /*   4-bytes little endian loop 2 start point */
  1471.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1472.             AlgoSampObjectGetLoopStart2(AlgoSampObj)))
  1473.             {
  1474.                 return eFileLoadDiskError;
  1475.             }
  1476.  
  1477.         /*   4-bytes little endian loop 2 end point */
  1478.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1479.             AlgoSampObjectGetLoopEnd2(AlgoSampObj)))
  1480.             {
  1481.                 return eFileLoadDiskError;
  1482.             }
  1483.  
  1484.         /*   4-bytes little endian loop 3 start point */
  1485.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1486.             AlgoSampObjectGetLoopStart3(AlgoSampObj)))
  1487.             {
  1488.                 return eFileLoadDiskError;
  1489.             }
  1490.  
  1491.         /*   4-bytes little endian loop 3 end point */
  1492.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1493.             AlgoSampObjectGetLoopEnd3(AlgoSampObj)))
  1494.             {
  1495.                 return eFileLoadDiskError;
  1496.             }
  1497.  
  1498.         /*   4-bytes little endian sampling rate */
  1499.         /*       should be between 100 and 65535 */
  1500.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1501.             AlgoSampObjectGetSamplingRate(AlgoSampObj)))
  1502.             {
  1503.                 return eFileLoadDiskError;
  1504.             }
  1505.  
  1506.         /*   4-byte little endian natural frequency fractional portion */
  1507.         /*       unsigned; divide by 2^32 to get the actual fraction */
  1508.         NaturalFreqTemp = AlgoSampObjectGetNaturalFrequency(AlgoSampObj);
  1509.         if (!WriteBufferedUnsignedLongLittleEndian(Output,
  1510.             (unsigned long)((NaturalFreqTemp - (long)NaturalFreqTemp) * 4294967296.0L)))
  1511.             {
  1512.                 return eFileLoadDiskError;
  1513.             }
  1514.  
  1515.         /*   4-byte little endian natural frequency integer portion */
  1516.         /*       total natural frequency should be between 0.01 and 1e6 */
  1517.         if (!WriteBufferedSignedLongLittleEndian(Output,(long)NaturalFreqTemp))
  1518.             {
  1519.                 return eFileLoadDiskError;
  1520.             }
  1521.  
  1522.         return eFileLoadNoError;
  1523.     }
  1524.  
  1525.  
  1526. /* mark the object as saved */
  1527. void                                    AlgoSampObjectMarkAsSaved(AlgoSampObjectRec* AlgoSampObj)
  1528.     {
  1529.         CheckPtrExistence(AlgoSampObj);
  1530.         if (AlgoSampObj->AlgoSampWindow != NIL)
  1531.             {
  1532.                 AlgoSampWindowWritebackModifiedData(AlgoSampObj->AlgoSampWindow);
  1533.             }
  1534.         AlgoSampObj->DataModified = False;
  1535.     }
  1536.